<?php
namespace app\index\controller;

use app\index\model\Devretention;
use app\index\model\LLogin;
use app\index\model\LRegister;
use app\index\controller\Server;
use think\Config;
use think\Controller;
use think\Log;

class Computebydevice extends Controller
{
    /*
     * 数组
     *
     * '1' 注册用户数，日活跃用户计算
     * '2' 次日留存计算
     * '3' 3日留存
     * '4' 4日留存
     * '5' 5日留存
     * '6' 6日留存
     * '7' 7日留存
     * '15' 15日留存
     * '30' 30日留存
     */
    private $nodes = [1, 2, 3, 4, 5, 6, 7, 15, 30];

    public function _initialize()
    {
        $this->lregister = new LRegister();
        $this->llogin    = new LLogin();
    }

    /**
     * 获取配置表开服日期
     * @return   [type]
     */
    public function getOpenDate()
    {
        # 记录开服日期
        # 
        $this->server = new Server();
        $this->new_open_date = $this->server->getOpenDate();
        
        return $this->new_open_date;
    }

    /**
     * 获取Character、Llogin、Lregister表最新记录
     *
     * @return   void
     */
    public function updateToRecent()
    {
        $Cronrecent = new Cronrecent();
        $Cronrecent->updateToRecent();
    }

    /**
     * 手动更新留存
     * @DateTime 2018-02-04
     * @return   [type]
     */
    public function manualUpdateRetention()
    {

        //更新最新的登录及注册记录
        $this->updateToRecent();

        //计算最新留存
        $this->doRetComputingToRecent();

        //返回成功信息
        $output['success'] = true;
        $output['msg']     = '完成数据更新';

        _callback($output);
    }

    /**
     * 从开服日开始执行留存计算
     * @DateTime 2018-02-02
     * @return   [type]
     */
    public function manualUpdateRetentionFromOpen()
    {

        /*
         * 免掉线
         */
        ignore_user_abort(true);

        /*
         * 不限时间
         */
        set_time_limit(0);

        //更新最新的登录及注册记录
        $this->updateToRecent();

        //开服日期
        $this->computeReversedFrom($this->getOpenDate(), true);
    }
    /**
     * 计算最近日期的留存率
     * @DateTime 2018-02-02
     * @return   [type]
     */
    public function doRetComputingToRecent($datefrom = null)
    {

        $recent_date = $datefrom ? $datefrom : $this->getMostRecentDate();

        //如果起始计算日期小于昨天
        //
        if ($recent_date) {

            $this->computeReversedFrom($recent_date, true);
        }
    }

    /**
     * 获取最新的计算日期
     *
     * 如果所计算的日期大于昨天则返回false，表示不必计算
     *
     * @return   void
     */
    public function getMostRecentDate()
    {

        // 留存表计算最近日期
        //
        $Devretention = new Devretention();
        $recent       = $Devretention->getRecentDate();

        // 如果最新日期已经大于等于昨天则不必计算，并返回false
        //
        if (strtotime($recent) >= strtotime(date('Y-m-d', strtotime("-1 day")))) {

            return false;
        } else {

            // 距今最近计算日期 = 最近日期 + 1天
            $compute_date = date('Y-m-d', (strtotime($recent) + 3600 * 24));
            return $compute_date;
        }
    }

    /**
     * 逆序留存计算
     * @return   void
     */
    public function computeReversedFrom($from_date, $by_device = false)
    {

        //留存计算终止日期

        $end_date = date("Y-m-d", strtotime("-1 day"));

        //起始日期到终止日期的天数

        $days = floor((strtotime($end_date) - strtotime($from_date)) / 86400);

        //开服日期

        $open_date = $this->getOpenDate();

        for ($i = 0; $i <= $days; $i++) {

            //起始计算日期
            //
            $startDate = date("Y-m-d", (strtotime($from_date) + 3600 * 24 * $i));

            //遍历留存计算日期
            //
            foreach ($this->nodes as $day) {

                //留存模型实例化
                //
                $model = new Devretention;

                //数据数组
                //
                $res = [];

                $regDate = $startDate;

                //玩家注册日期和开服时间比较,如果注册日期大于开服日期，计算该节点用户留存

                if (strtotime($regDate) >= strtotime($open_date)) {

                    if (1 === $day) {

                        $res = [];

                        //计算新注册人数及日活跃人数

                        $res['date']        = $regDate;
                        $res['DAU']         = $this->llogin->getDAU($regDate, $by_device);
                        $res['register']    = $this->lregister->getRegTotal($regDate);
                        $res['total']       = $this->lregister->getRegGrandTotal($regDate);
                        $res['create_time'] = date('Y-m-d H:i:s');
                        //dump($res);

                        //保存昨天的新注册及日活跃人数

                        $model->isUpdate(false)->save($res);

                    } else if (1 < $day) {

                        $res_ret = [];

                        //计算日期
                        //
                        $regDate = date('Y-m-d', strtotime($startDate) - 3600 * 24 * ($day - 1));

                        if ($regDate >= $open_date) {

                            $calcDate        = $startDate;
                            $res_ret['date'] = $regDate;

                            //计算注册日期开始，第 $day 天的留存数

                            $res_ret['RET' . $day] = $this->llogin->getRET($regDate, $calcDate, $by_device);
                            //dump($res_ret);

                            //更新注册日期开始，第 $day 天的留存数

                            $model->isUpdate(true)->save($res_ret, ['date' => $regDate]);
                        }
                    }
                }
            }
        }
    }
}
